/*
 * Copyright (c) 2024. hallele, Inc All rights reserved.
 */

package cn.hallele.ms.infrastructure.core.aspect.controller.children;

import cn.hallele.infrastructure.metadata.constant.MsgCodeConst;
import cn.hallele.infrastructure.metadata.io.Response;
import cn.hallele.ms.infrastructure.core.aspect.controller.BaseExceptionAspect;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.authority.AuthorityException;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeException;
import com.alibaba.csp.sentinel.slots.block.flow.FlowException;
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowException;
import com.alibaba.csp.sentinel.slots.system.SystemBlockException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.MessageSource;
import org.springframework.core.annotation.Order;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

/**
 * Sentinel相关异常处理
 *
 * @author anle5
 * @since 2024/9/16 19:43
 */
@Slf4j
@RestControllerAdvice
@Order(10)
public class SentinelExceptionAspect extends BaseExceptionAspect {
    /**
     * 国际化
     *
     * @param i18n 国际化
     */
    public SentinelExceptionAspect(MessageSource i18n) {
        super(i18n);
    }

    /**
     * 拦截所有 {@link FlowException}
     *
     * @param e FlowException
     * @return 错误响应
     */
    @ExceptionHandler(FlowException.class)
    public Response<?> flowException(FlowException e) {
        String msgCode = e.getMessage();
        String msgDesc = i18n.getMessage(msgCode, new Object[]{}, MsgCodeConst.SENTINEL_SERVICE_RATE_LIMITING, getLocale());
        log.error("Find a FlowException. MsgCode: {}, msgDesc: {}.", msgCode, msgDesc, e);
        return buildResponse(msgCode, msgDesc);
    }

    /**
     * 拦截所有 {@link DegradeException}
     *
     * @param e DegradeException
     * @return 错误响应
     */
    @ExceptionHandler(DegradeException.class)
    public Response<?> blockException(DegradeException e) {
        String msgCode = e.getMessage();
        String msgDesc = i18n.getMessage(msgCode, new Object[]{}, MsgCodeConst.SENTINEL_SERVICE_RATE_FUSING, getLocale());
        log.error("Find a DegradeException. MsgCode: {}, msgDesc: {}.", msgCode, msgDesc, e);
        return buildResponse(msgCode, msgDesc);
    }

    /**
     * 拦截所有 {@link ParamFlowException}
     *
     * @param e ParamFlowException
     * @return 错误响应
     */
    @ExceptionHandler(ParamFlowException.class)
    public Response<?> blockException(ParamFlowException e) {
        String msgCode = e.getMessage();
        String msgDesc = i18n.getMessage(msgCode, new Object[]{}, MsgCodeConst.SENTINEL_HOTSPOT_RESOURCES_RATE_LIMITING, getLocale());
        log.error("Find a ParamFlowException. MsgCode: {}, msgDesc: {}.", msgCode, msgDesc, e);
        return buildResponse(msgCode, msgDesc);
    }

    /**
     * 拦截所有 {@link SystemBlockException}
     *
     * @param e SystemBlockException
     * @return 错误响应
     */
    @ExceptionHandler(SystemBlockException.class)
    public Response<?> blockException(SystemBlockException e) {
        String msgCode = e.getMessage();
        String msgDesc = i18n.getMessage(msgCode, new Object[]{}, MsgCodeConst.SENTINEL_SYSTEM_ADAPTIVELY_LIMITS, getLocale());
        log.error("Find a SystemBlockException. MsgCode: {}, msgDesc: {}.", msgCode, msgDesc, e);
        return buildResponse(msgCode, msgDesc);
    }

    /**
     * 拦截所有 {@link AuthorityException}
     *
     * @param e AuthorityException
     * @return 错误响应
     */
    @ExceptionHandler(AuthorityException.class)
    public Response<?> blockException(AuthorityException e) {
        String msgCode = e.getMessage();
        String msgDesc = i18n.getMessage(msgCode, new Object[]{}, MsgCodeConst.SENTINEL_NO_AUTHORIZATION, getLocale());
        log.error("Find a AuthorityException. MsgCode: {}, msgDesc: {}.", msgCode, msgDesc, e);
        return buildResponse(msgCode, msgDesc);
    }

    /**
     * 拦截所有 {@link BlockException}
     *
     * @param e BlockException
     * @return 错误响应
     */
    @ExceptionHandler(BlockException.class)
    public Response<?> blockException(BlockException e) {
        String msgCode = e.getMessage();
        String msgDesc = i18n.getMessage(msgCode, new Object[]{}, MsgCodeConst.SENTINEL_ERROR, getLocale());
        log.error("Find a BlockException. MsgCode: {}, msgDesc: {}.", msgCode, msgDesc, e);
        return buildResponse(msgCode, msgDesc);
    }
}
